#ifndef CONSTANT_H
#define CONSTANT_H

#include <stdint.h>
#include <stddef.h>
#include <set>
#include <array>
#include <string>

namespace dymy
{
typedef int card_t;
typedef card_t card_type_t;
typedef card_t card_num_t;
typedef card_t CARD_t;

typedef size_t card_size_t;
typedef uint32_t ID_t;
typedef std::multiset<card_t> multiple_card_t;

constexpr card_type_t UNKNOW = 0x00 << 4;
constexpr card_type_t SPADE = 0x01 << 4;   //黑桃
constexpr card_type_t HEART = 0X02 << 4;   //红桃
constexpr card_type_t DIAMOND = 0x04 << 4; //方块
constexpr card_type_t CLUB = 0x08 << 4;    //梅花

constexpr card_type_t MASK = 0xf;

constexpr int PERSON_STEP_WAITING = 0x00;       //刚进入房间，无状态
constexpr int PERSON_STEP_ALLOT_WAITING = 0x01; //抢地主，但还没轮到你
constexpr int PERSON_STEP_ALLOT_PROCESS = 0x02; //正在轮到你抢地主
constexpr int PERSON_STEP_ALLOT_REJECT = 0x03;  //你没抢地主
//constexpr int PERSON_STEP_ALLOT_ALLOW = 0x04; //你抢地主了
constexpr int PERSON_STEP_PLAING = 0x04;            // 你开始出牌
constexpr int PERSON_STEP_PLAING_WAITING = 0x11;    //还没轮到你出牌
constexpr int PERSON_STEP_PLAING_NOT_AFFORD = 0x12; //你要不起
constexpr int PERSON_STEP_PLAING_YET = 0x13;        //你出过牌了（存下你的牌）
constexpr int PERSON_STEP_FINISHED_SUCCESS = 0x21;  //你胜利了
constexpr int PERSON_STEP_FINISHED_FAILED = 0x22;   //你失败了

constexpr int STEP_SHIFT = 4;
constexpr int STEP_MASK = (0xf);
constexpr int STEP_WATING = (0x01 << STEP_SHIFT);   //正在等待用户进来
constexpr int STEP_ALLOT = (0x02 << STEP_SHIFT);    //正在确认谁在抢地主
constexpr int STEP_PLAYING = (0x04 << STEP_SHIFT);  //正在出牌
constexpr int STEP_FINISHED = (0x08 << STEP_SHIFT); //游戏结束

constexpr int ERROR_PROCESS = -100;            //流程错误
constexpr int ERROR_EMPTY_PERSON = -99;        //没有此人
constexpr int ERROR_NOT_SELF = -98;            //没有轮到本人操作
constexpr int ERROR_PLAYING_LACK_PERSON = -97; //开始游戏但是人员不齐
constexpr int ERROR_PLAYING_NOT_PREPARE = -96; //开始游戏但是人员没有准备
constexpr int ERROR_CARDS = -95;               //开始游戏但是人员没有准备

extern const int REP_CODE_SUCCESS;
extern const std::string REP_MESSAGE_SUCCESS;

extern const int REP_CODE_ERROR_UNKNOW;
extern const std::string REP_MESSAGE_ERROR_UNKNOW;

extern const int REP_CODE_ERROR_USER_EXISTS;
extern const std::string REP_MESSAGE_ERROR_USER_EXISTS;

extern const int REP_CODE_ERROR_FULL_USERS;
extern const std::string REP_MESSAGE_ERROR_FULL_USERS;

extern const int REP_CODE_ERROR_INVALID_USER_NAME;
extern const std::string REP_MESSAGE_ERROR_INVALID_USER_NAME;

extern const int REP_CODE_ERROR_INVALID_USER_PASSWORD;
extern const std::string REP_MESSAGE_ERROR_INVALID_USER_PASSWORD;

extern const int REP_CODE_ERROR_INVALID_TABLE_ID;
extern const std::string REP_MESSAGE_ERROR_INVALID_TABLE_ID;

extern const int REP_CODE_ERROR_INVALID_TABLE_INDEX;
extern const std::string REP_MESSAGE_ERROR_INVALID_TABLE_INDEX;

extern const int REP_CODE_ERROR_TABLE_INDEX_BUSY;
extern const std::string REP_MESSAGE_ERROR_TABLE_INDEX_BUSY;

extern const int REP_CODE_ERROR_TABLE_NOT_EXISTS_USER;
//    extern const std::string REP_MESSAGE_ERROR_TABLE_NOT_EXISTS_USER = "该位置不存在该用户";
//    extern const std::string REP_MESSAGE_ERROR_TABLE_NOT_EXISTS_USER ="该位置不存在该用户";

extern const std::string REP_MESSAGE_ERROR_TABLE_NOT_EXISTS_USER;

extern const int REP_CODE_ERROR_TABLE_INVALID_PROCESS;
//    extern const std::string REP_MESSAGE_ERROR_TABLE_INVALID_PROCESS = "牌桌流程错误";
extern const std::string REP_MESSAGE_ERROR_TABLE_INVALID_PROCESS;

extern const int REP_CODE_ERROR_TABLE_NOT_SELF;
//    extern const std::string REP_MESSAGE_ERROR_TABLE_NOT_SELF = "还没轮到你操作";
extern const std::string REP_MESSAGE_ERROR_TABLE_NOT_SELF;

extern const int REP_CODE_ERROR_TABLE_ALREADY_PREPARED;
//    extern const std::string REP_MESSAGE_ERROR_TABLE_ALREADY_PREPARED_OR_NOT_PREPARED = "你已经处于该(准备或空闲)状态了";
extern const std::string REP_MESSAGE_ERROR_TABLE_ALREADY_PREPARED;

extern const int REP_CODE_ERROR_TABLE_ALREADY_NOT_PREPARED;
//    extern const std::string REP_MESSAGE_ERROR_TABLE_ALREADY_PREPARED_OR_NOT_PREPARED = "你已经处于该(准备或空闲)状态了";
extern const std::string REP_MESSAGE_ERROR_TABLE_ALREADY_NOT_PREPARED;

extern const int REP_CODE_ERROR_TABLE_ALREADY_JOIN;
extern const std::string REP_MESSAGE_ERROR_TABLE_ALREADY_JOIN;

extern const int REP_CODE_ERROR_TABLE_NOT_JOIN;
//    extern const std::string REP_MESSAGE_ERROR_TABLE_NOT_JOIN = "你还不在这个桌子上";
extern const std::string REP_MESSAGE_ERROR_TABLE_NOT_JOIN;

extern const int REP_CODE_ERROR_TABLE_INVALID_CARDS;
extern const std::string REP_MESSAGE_ERROR_TABLE_INVALID_CARDS;

extern const int REP_CODE_ERROR_LOGIN_REPLACE;
extern const std::string REP_MESSAGE_ERROR_LOGIN_REPLACE;

extern const int REP_CODE_ERROR_TABLE_REPEAT_JOIN;
extern const std::string REP_MESSAGE_ERROR_TABLE_REPEAT_JOIN;

extern const int REP_CODE_ERROR_SQL;
extern const std::string REP_MESSAGE_ERROR_SQL;

extern const int REP_CODE_ERROR_LOGIN_INVALID_TOKEN;
extern const std::string REP_MESSAGE_ERROR_LOGIN_INVALID_TOKEN;

constexpr int REQ_TYPE_REGISTER = 1;
constexpr int REP_TYPE_REGISTER = REQ_TYPE_REGISTER;

constexpr int REQ_TYPE_LOGIN = 2;
constexpr int REP_TYPE_LOGINN = REQ_TYPE_LOGIN;

constexpr int REQ_TYPE_RESET_PWD = 3;
constexpr int REP_TYPE_RESET_PWD = REQ_TYPE_RESET_PWD;

constexpr int REQ_TYPE_ADD_PERSON = 4;
constexpr int REP_TYPE_ADD_PERSON = REQ_TYPE_ADD_PERSON;

constexpr int REQ_TYPE_PREPARED = 5;
constexpr int REP_TYPE_PREPARED = REQ_TYPE_PREPARED;

constexpr int REQ_TYPE_ROB_LANDLORD = 6;
constexpr int REP_TYPE_ROB_LANDLORD = REQ_TYPE_ROB_LANDLORD;

constexpr int REQ_TYPE_PLAY_CARDS = 7;
constexpr int REP_TYPE_PLAY_CARDS = REQ_TYPE_PLAY_CARDS;

constexpr int REQ_TYPE_SERVER_INFO = 8;
constexpr int REP_TYPE_SERVER_INFO = REQ_TYPE_SERVER_INFO;

constexpr int REQ_TYPE_TABLE_INFO = 9;
constexpr int REP_TYPE_TABLE_INFO = REQ_TYPE_TABLE_INFO;

constexpr int REQ_TYPE_CHAT = 10;
constexpr int REP_TYPE_CHAT = REQ_TYPE_CHAT;

constexpr int REQ_TYPE_CHAT_TABLE = 11;
constexpr int REP_TYPE_CHAT_TABLE = REQ_TYPE_CHAT_TABLE;

constexpr int REP_TYPE_PERSON_CHANGED_NOTIFY = 12;

constexpr int REP_TYPE_PERSON_CONNECTED = 13;
extern const std::string SOCKET_URL;

constexpr inline card_t encode_card(card_type_t type, card_num_t num) noexcept
{
    return type | num;
}

constexpr inline card_type_t decode_card_type(card_t card) noexcept
{
    return card & ~MASK;
}
constexpr inline card_num_t decode_card_num(card_t card) noexcept
{
    return card & MASK;
}

}

#endif // CONSTANT_H
